/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package br.uniceub.fsw.agenda.model.dao;

import br.uniceub.fsw.agenda.exception.BusinessException;
import br.uniceub.fsw.agenda.exception.ChildConstraintViolationException;
import br.uniceub.fsw.agenda.exception.DatabaseException;
import br.uniceub.fsw.agenda.exception.UniqueConstraintException;
import br.uniceub.fsw.agenda.model.vo.PessoaVO;
import br.uniceub.fsw.agenda.model.vo.LogradouroVO;
import java.sql.PreparedStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author Bruno
 */
public class PessoaDAO extends GenericDAO {
    
    public PessoaDAO(Connection con) {
        super(con);
    }   
    
    public List<PessoaVO> findAll() throws BusinessException, DatabaseException {
        //montar string de consulta
        StringBuilder query = new StringBuilder();
        query.append("SELECT * FROM TB_PESSOA ORDER BY NO_PESSOA");
        
        //lista que vai armazenar os objetos Pessoa da consulta
        List<PessoaVO> resultado = new ArrayList<PessoaVO>();
        
        try {
            
            //objeto con é herdado da super classe
            Statement st = con.createStatement();
            ResultSet rs = st.executeQuery(query.toString());
            while (rs.next()) {
                PessoaVO pessoa = new PessoaVO();
                
                pessoa.setIdPessoa(rs.getInt("ID_PESSOA"));
                pessoa.setNoPessoa(rs.getString("NO_PESSOA"));
                pessoa.setNrCpf(rs.getLong("NR_CPF"));
                pessoa.setDsComplemento(rs.getString("DS_COMPLEMENTO"));
                pessoa.setNrNumero(rs.getInt("NR_NUMERO"));
                
                LogradouroDAO logradouroDAO = new LogradouroDAO(this.con);
                
                LogradouroVO logradouro = logradouroDAO.findById(rs.getInt("ID_LOGRADOURO"));
                
                pessoa.setLogradouro(logradouro);
                
                resultado.add(pessoa);
            }
            
            st.close();
            rs.close();
            
            return resultado;            
        } catch (SQLException ex) {
            ex.printStackTrace();
            throw new DatabaseException("Erro ao buscar Pessoa", ex);            
        }        
    }

    public List<PessoaVO> findAllByNome(String noPessoa) throws BusinessException, DatabaseException {
        //montar string de consulta
        StringBuilder query = new StringBuilder();
        query.append("SELECT * FROM TB_PESSOA WHERE UPPER(NO_PESSOA) LIKE UPPER(?) ORDER BY NO_PESSOA");
        
        //lista que vai armazenar os objetos Pessoa da consulta
        List<PessoaVO> resultado = new ArrayList<PessoaVO>();
        
        try {
            
            //objeto con é herdado da super classe
            PreparedStatement st = con.prepareStatement(query.toString());
            String filtro = "%" + noPessoa + "%";
            
            st.setString(1, filtro);
            ResultSet rs = st.executeQuery();
            while (rs.next()) {
                PessoaVO pessoa = new PessoaVO();
                
                pessoa.setIdPessoa(rs.getInt("ID_PESSOA"));
                pessoa.setNoPessoa(rs.getString("NO_PESSOA"));
                pessoa.setNrCpf(rs.getLong("NR_CPF"));
                pessoa.setDsComplemento(rs.getString("DS_COMPLEMENTO"));
                pessoa.setNrNumero(rs.getInt("NR_NUMERO"));
                
                LogradouroDAO logradouroDAO = new LogradouroDAO(this.con);
                
                LogradouroVO logradouro = logradouroDAO.findById(rs.getInt("ID_LOGRADOURO"));
                
                pessoa.setLogradouro(logradouro);
                
                resultado.add(pessoa);
            }
            
            st.close();
            rs.close();
            
            return resultado;            
        } catch (SQLException ex) {
            ex.printStackTrace();
            throw new DatabaseException("Erro ao buscar Lista de Pessoa", ex);            
        }        
    }

    public PessoaVO findByCpf(Long nrCpf) throws BusinessException, DatabaseException {
        //montar string de consulta
        StringBuilder query = new StringBuilder();
        query.append("SELECT * FROM TB_PESSOA WHERE NR_CPF = ?");
        
        PessoaVO pessoa = new PessoaVO();
        
        try {
            
            //objeto con é herdado da super classe
            PreparedStatement st = con.prepareStatement(query.toString());
            st.setString(1, nrCpf.toString());
            ResultSet rs = st.executeQuery();
            while (rs.next()) {
                pessoa.setIdPessoa(rs.getInt("ID_PESSOA"));
                pessoa.setNoPessoa(rs.getString("NO_PESSOA"));
                pessoa.setNrCpf(rs.getLong("NR_CPF"));
                pessoa.setDsComplemento(rs.getString("DS_COMPLEMENTO"));
                pessoa.setNrNumero(rs.getInt("NR_NUMERO"));
                
                LogradouroDAO logradouroDAO = new LogradouroDAO(this.con);
                
                LogradouroVO logradouro = logradouroDAO.findById(rs.getInt("ID_LOGRADOURO"));
                
                pessoa.setLogradouro(logradouro);
            }
            
            st.close();
            rs.close();
            
            return pessoa;
        } catch (SQLException ex) {
            ex.printStackTrace();
            throw new DatabaseException("Erro ao buscar Pessoa", ex);            
        }        
    }

    public PessoaVO findById(Integer idPessoa) throws BusinessException, DatabaseException {
        //montar string de consulta
        StringBuilder query = new StringBuilder();
        query.append("SELECT * FROM TB_PESSOA WHERE ID_PESSOA = ?");
        
        PessoaVO pessoa = new PessoaVO();
        
        try {
            
            //objeto con é herdado da super classe
            PreparedStatement st = con.prepareStatement(query.toString());
            st.setString(1, idPessoa.toString());
            ResultSet rs = st.executeQuery();
            while (rs.next()) {
                pessoa.setIdPessoa(rs.getInt("ID_PESSOA"));
                pessoa.setNoPessoa(rs.getString("NO_PESSOA"));
                pessoa.setNrCpf(rs.getLong("NR_CPF"));
                pessoa.setDsComplemento(rs.getString("DS_COMPLEMENTO"));
                pessoa.setNrNumero(rs.getInt("NR_NUMERO"));
                
                LogradouroDAO logradouroDAO = new LogradouroDAO(this.con);
                
                LogradouroVO logradouro = logradouroDAO.findById(rs.getInt("ID_LOGRADOURO"));
                
                pessoa.setLogradouro(logradouro);
            }
            
            st.close();
            rs.close();
            
            return pessoa;
        } catch (SQLException ex) {
            ex.printStackTrace();
            throw new DatabaseException("Erro ao buscar Pessoa", ex);            
        }        
    }

    /**
     * Faz o insert de uma nova pessoa e devolve a o id recem gerado
     * @param Pessoa pessoa que se deseja inserir
     * @return ID auto-increment gerado para esse registro
     * @throws br.uniceub.fsw.agenda.exception.BusinessException
     * @throws br.uniceub.fsw.agenda.exception.DatabaseException
     */
    public Integer insert(PessoaVO pessoa) throws BusinessException, DatabaseException {        
        StringBuilder query = new StringBuilder();
        query.append("INSERT INTO TB_PESSOA(NO_PESSOA, NR_CPF, ID_LOGRADOURO, DS_COMPLEMENTO, NR_NUMERO) ");
        query.append("VALUES (?,?,?,?,?)");
        
        //retornar id gerado
        Integer generatedId = null;
        
        try {           
            PreparedStatement st = con.prepareStatement(query.toString());
            st.setString(1, pessoa.getNoPessoa());
            st.setString(2, pessoa.getNrCpf().toString());
            st.setString(3, pessoa.getLogradouro().getIdLogradouro().toString());
            st.setString(4, pessoa.getDsComplemento());
            st.setString(5, pessoa.getNrNumero().toString());
            
            st.executeUpdate();
            
            //pegar id gerado
            ResultSet rs = st.getGeneratedKeys();
            while (rs.next()) {
                generatedId = new Integer(rs.getString(1));                
            }                    
            
            return generatedId;            
        } catch (SQLException ex) {            
            ex.printStackTrace();
            if (ex.getErrorCode() == 1062) {
                throw new UniqueConstraintException(ex.getMessage(), ex);                
            }
            throw new DatabaseException("Erro no DAOPessoa.insert()", ex);            
        }      
    }

    /**
     * Faz o update de uma pessoa
     * @param Pessoa pessoa que se deseja alterar
     * @return 0
     * @throws br.uniceub.fsw.agenda.exception.BusinessException
     * @throws br.uniceub.fsw.agenda.exception.DatabaseException
     */
    public Integer update(PessoaVO pessoa) throws BusinessException, DatabaseException {        
        StringBuilder query = new StringBuilder();
        query.append("UPDATE TB_PESSOA SET NO_PESSOA = ?, NR_CPF = ?, ID_LOGRADOURO = ?, DS_COMPLEMENTO = ?, NR_NUMERO = ? ");
        query.append("WHERE ID_PESSOA = ?");
        
        try {           
            PreparedStatement st = con.prepareStatement(query.toString());
            st.setString(1, pessoa.getNoPessoa());
            st.setString(2, pessoa.getNrCpf().toString());
            st.setString(3, pessoa.getLogradouro().getIdLogradouro().toString());
            st.setString(4, pessoa.getDsComplemento());
            st.setString(5, pessoa.getNrNumero().toString());
            st.setString(6, pessoa.getIdPessoa().toString());
            
            st.executeUpdate();
            
            return 0;
        } catch (SQLException ex) {            
            ex.printStackTrace();
            throw new DatabaseException("Erro no DAOPessoa.update()", ex);            
        }      
    }

    public void delete(Integer idPessoa) throws BusinessException, DatabaseException {
        String query = "DELETE FROM TB_PESSOA WHERE ID_PESSOA = ?";
        
        try {
            PreparedStatement st = con.prepareStatement(query);
            st.setInt(1, idPessoa);
            st.executeUpdate();
        } catch (SQLException ex) {            
            ex.printStackTrace();
            if (ex.getErrorCode() == 1451) {
                throw new ChildConstraintViolationException(ex.getMessage(), ex);                
            }
            throw new DatabaseException("Erro no DAOPessoa.delete()", ex);
        }
    }
    
}
